package com.hama.iotrust.common.mybatis.criteria;

import java.util.HashMap;
import java.util.Map;

import com.hama.iotrust.common.mybatis.criteria.Criteria;
import com.hama.iotrust.common.mybatis.criteria.CriteriaException;
import com.hama.iotrust.common.mybatis.criteria.Expression;

/**
 * SQL基本表达式 <, >, <= , >=, =, <>
 * 
 * @param <T>
 * @author 金建强(ptma@163.com)
 * @version 1.0.0
 * @since 2013-4-2 11:23:16
 */
public class SimpleExpression implements Expression {

    public enum Operator {

        LessThen("<"), GreaterThen(">"), LessEqual("<="), GreaterEqual(">="), Equal("="), NotEqual("<>");

        private final String m_op;

        Operator(String op){
            m_op = op;
        }

        @Override
        public String toString() {
            return m_op;
        }

        public static Operator fromString(String text) {
            if (text != null) {
                for (Operator b : Operator.values()) {
                    if (text.equalsIgnoreCase(b.m_op)) {
                        return b;
                    }
                }
            }
            return null;
        }
    };

    private String      m_propName;
    private String      m_columnName = null;
    private Operator    m_operator;
    private Object      m_value;
    private String      m_param;
    private Criteria<?> m_crit;

    SimpleExpression(String propertyName, Operator op, Object value){
        m_propName = propertyName;
        m_operator = op;
        m_value = value;
    }

    public String getSql() {
        StringBuilder sb = new StringBuilder();
        sb.append("(");
        if (m_columnName == null) {
            sb.append("< not bound:").append(m_propName).append(">");
        } else {
            sb.append(m_columnName);
        }
        m_param = m_propName + m_crit.nextParamSuffix();
        sb.append(" ").append(m_operator).append(" #{" + Criteria.PARAM_PREFIX + m_param + "})");
        return sb.toString();
    }

    public Map<String, Object> getParameter() {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put(m_param, m_value);
        return map;
    }

    public boolean verify(Criteria<?> criteria) {
        return criteria.hasProperty(m_propName) && criteria.checkType(m_propName, m_value.getClass());
    }

    public void bind(Criteria<?> crit) throws CriteriaException {
        m_crit = crit;
        m_columnName = crit.toColumnName(m_propName);
    }
}
